package com.zx.flow.core.service;

import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.zx.flow.api.dict.FlowDict.Event;
import com.zx.flow.api.execute.model.FlowContext;
import com.zx.flow.api.execute.request.FlowParam;
import com.zx.flow.api.execute.response.FlowResult;
import com.zx.flow.api.util.TraceUtil;
import com.zx.flow.api.util.Util;
import com.zx.flow.db.dao.FlowTraceDao;
import com.zx.flow.db.entity.FlowTraceEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

/**
 * @author zhangxue
 */
@Service
@Slf4j
public class FlowTraceService {

    @Autowired
    private FlowTraceDao traceDao;

    public static void trace(FlowParam param, FlowResult result) {
        try {
            JSONObject json = JSON.parseObject(JSON.toJSONString(param));
            String accountCode = json.getString("accountCode");

            String eventCode = json.getString("event");
            eventCode = StringUtils.isEmpty(eventCode) ? json.getString("eventCode") : eventCode;
            Event event = Event.getByCode(eventCode);

            String nodeId = json.getString("nodeId");
            FlowTraceService service = SpringUtil.getBean(FlowTraceService.class);

            service.save(accountCode, event, result.getFlowContext(), nodeId, param, result);
        } catch (Exception e) {
            log.error("", e);
        }
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void save(String accountCode, Event event, FlowContext flow, String nodeId, FlowParam param,
            FlowResult result) {
        FlowTraceEntity trace = new FlowTraceEntity();
        trace.setTraceId(TraceUtil.getTraceId());
        trace.setSpanId(TraceUtil.getSpanId());
        trace.setAccountCode(accountCode);
        if (event != null) {
            trace.setEventCode(event.getCode());
            trace.setEventTypeCode(event.getEventType().getCode());
        }
        if (flow != null) {
            trace.setFlowId(flow.getId());
            trace.setFlowCode(flow.getFlowConfigCode());
        }
        trace.setNodeId(nodeId);
        trace.setRequest(param == null ? "" : Util.getJsonStr(param));
        if (result != null) {
            trace.setResponseStatus(result.getStatus().getCode());
            trace.setResponseMsg(result.getMsg());
        }

        this.traceDao.insert(trace);
    }

}
